﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

using agree.schema;
using agree.mrs;

using alib;
using alib.BitArray;
using alib.Collections;
using alib.Collections.ReadOnly;
using alib.Combinatorics;
using alib.Debugging;
using alib.Enumerable;
using alib.Reflection;
using alib.String;

namespace agree.transfer
{
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// 
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	public class TransferRules : IdentList<TransferRule>
	{
		public static readonly TransferRules None;

		static TransferRules()
		{
			None = new TransferRules(SysObj.Instance);
		}

		public TransferRules(IIdentity prv)
			: base(prv)
		{
		}

		public void load()
		{
			TransferRule r;

			r = new TransferRule(this);
			r.load1();
			base.Add(r);

			r = new TransferRule(this);
			r.load2();
			base.Add(r);

			r = new TransferRule(this);
			r.load3();
			base.Add(r);

			r = new TransferRule(this);
			r.load4();
			base.Add(r);

			r = new TransferRule(this);
			r.load5();
			base.Add(r);


		}
	};


	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// 
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

	[DebuggerDisplay("{ToString(),nq}")]
	public class TransferRule : identity_named, ISemantics, IEnumerable
	{
		int var_num;

		public TransferRule(TransferRules rm, String name)
			: base(rm, name)
		{
			this.L1.a = Collection<Relation>.None;
			this.L2.a = Collection<Relation>.None;
		}

		public TransferRule(TransferRules rm)
			: this(rm, default(String))
		{
		}

		public bag<Relation> L1;

		public bag<Relation> L2;

		public IEnumerator GetEnumerator() { throw not.impl; }

		public Constant RegisterConstant(String value)
		{
			throw new NotImplementedException();
		}
		public Variable CreateInstance(System.Type sem_type)
		{
			if (sem_type == typeof(mrs.type.H))
				return new Handle(this, var_num++);
			if (sem_type == typeof(mrs.type.E))
				return new Event(this, var_num++);
			return new Variable(this, sem_type.Name.ToLower(), var_num++);
		}
		public SemType GetSemType<T>() where T : SemType
		{
			throw new NotImplementedException();
		}

		public override String ToString()
		{
			return String.Format("{0}", base.Name);
		}

		/////////////////////////////////////////////////////////////

		public void load1()
		{
			Name = "its_raining_rule";
			var x0 = CreateInstance(typeof(mrs.type.X));
			var e1 = CreateInstance(typeof(mrs.type.E));

			L1.AddRange(
				new Relation(this) { PRED = "exist_q_rel", ARG0 = x0 },
				new Relation(this) { PRED = "_fall_v_1_rel", ARG0 = e1, ARG1 = x0 },
				new Relation(this) { PRED = "_rain_n_1_rel", ARG0 = x0 }
			);
			L2.AddRange(
				new Relation(this) { PRED = "_rain_v_1_rel", ARG0 = e1 }
			);
		}

		public void load2()
		{
			Name = "lbl_wiring_rule";
			var h1 = CreateInstance(typeof(mrs.type.H));

			L1.AddRange(
				new Relation(this) { LBL = (Handle)h1 }
			);
			L2.AddRange(
				new Relation(this) { LBL = (Handle)h1 }
			);
		}

		public void load3()
		{
			Name = "arg0_x_wiring_rule";
			var x1 = CreateInstance(typeof(mrs.type.X));
			L1.AddRange(
				new Relation(this) { ARG0 = (Variable)x1 }
			);
			L2.AddRange(
				new Relation(this) { ARG0 = (Variable)x1 }
			);

		}

		public void load4()
		{
			Name = "arg0_e_wiring_rule";
			var e1 = CreateInstance(typeof(mrs.type.E));
			L1.AddRange(
				new Relation(this) { ARG0 = (Variable)e1 }
			);
			L2.AddRange(
				new Relation(this) { ARG0 = (Variable)e1 }
			);
		}


		public void load5()
		{
			Name = "arg1_wiring_rule";
			var x1 = CreateInstance(typeof(mrs.type.X));
			L1.AddRange(
				new Relation(this) { ARG1 = (Variable)x1 }
			);
			L2.AddRange(
				new Relation(this) { ARG1 = (Variable)x1 }
			);
		}
	};
}